import React, { Component } from 'react'

/*
    组件通信
        为了组件拆分
        父子关系- 重要常用
        兄弟关系- 自定义事件模式产生技术方案 eventBus/ 通过共同的父组件的通信
        其他关系- mobx / redux / 基于hook的方案
*/
/*
    父子传参：子组件通过props接收传值
        类组件： this.props
        函数式组件： 获取参数的props对象
*/

// 函数子组件
function SonF(props) {             // 函数式组件接收父组件传值     // 这里解构 function SonF({ msg, list, userInfo, getMsg, child }) {  
    // props是一个对象，存储父组件传过来的所有数据
    // console.log(props);
    // 对 props 解构赋值
    const { msg, list, userInfo, getMsg, child } = props       // 重定义解构，也可以直接在接收参数的时候解构
    return (
        <div>
            函数子组件，{props.msg}
            {/* <div>{props.list}</div> // 这样会展示为 123，相当于 toString 之后的， 没有vue那样的处理，所以数组传递过来需要直接遍历 */}
            {/* 数组传递 */}
            <div>{props.list.map(item => <p key={item}>{item}</p>)}</div>
            {/* 对象传递 */}
            <div>{props.userInfo.name}</div>
            {/* 函数传递/事件传递 */}
            <button onClick={props.getMsg}>父组件传入的事件函数</button>
            {/* 父组件的jsx直接渲染 */}
            {props.child}
            <div>
                {msg}
                <div>{list.map(item => <p key={item}>{item}</p>)}</div>
                <div>{userInfo.name}</div>
                <button onClick={getMsg}>父组件传入的事件函数</button>
                {child}
            </div>
        </div>
    )
}

// 类子组件
class SonC extends Component {
    render() {
        return (
            // 类组件通过this 获取props
            <div>类子组件, {this.props.msg}</div>
        )
    }
}

/*
    props是只读的，要满足单向数据流的要求，子组件只能读取props中的数据，不能进行修改
    可以传递任意类型：数字、字符串、布尔、数组、对象、函数、jsx
*/
/*
    父传子： props 、 函数
    子传父： 子组件调用父组件传递过来的函数，并且把想要传递的数据当成函数的实参传入
*/

// 函数子组件, 子传父
function Son({ getSonMsg }) {  
    const handleClick = function() {
        getSonMsg('子组件再次传递给父组件的实参')
    }         
    const senMsg = function() {
        getSonMsg('通过父组件传给兄弟组件的信息')
    } 
    return (
        <div>
            子组件

            <button onClick={() => getSonMsg('子传父的实参')}>传递给父组件</button>
            <button onClick={handleClick}>传递给父组件</button>
            <button onClick={senMsg}>传递给兄弟组件</button>
        </div>
    )
}


// 父组件
export default class Test6_com_props extends Component {
    state = {
        message: 'this is msg',
        list: [1, 2, 3],
        userInfo: {
            name: 'lili'
        },
        
    }
    getMsg = () => {
        console.log('函数传递');
    }

    getSonMsg = (sonMsg) => {
        console.log(sonMsg);

        this.setState({
            message: sonMsg
        })
    }
    render() {
        return (
            <div>
                {/* 父组件传参，在子组件上绑定属性，属性名可以自定义，子组件会接收这个属性 */}
                <SonF 
                    msg={this.state.message} 
                    list={this.state.list} 
                    userInfo={this.state.userInfo}
                    getMsg={this.getMsg}
                    child={<p>父组件的jsx</p>} />
                <SonC msg={this.state.message} />

                <Son getSonMsg={this.getSonMsg} />
            </div>
        )
    }
}
